package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fx_swift_forex/api"
	"fx_swift_forex/internal/model"
	"fx_swift_forex/pkg/code"
	"fx_swift_forex/pkg/global"
	"fx_swift_forex/pkg/internalerrors"
	"github.com/spf13/cast"
	"mime/multipart"
	"strings"
)

type IConvertSrv interface {
	// 获取报价
	RateDetailed(ctx context.Context, req *api.RateDetailedReq) (*api.RateDetailedRes, error)
	// 报价转化
	Conversions(ctx context.Context, req *api.ConversionsReq) error
}
type convertSrv struct {
}

func NewConvertSrv() IConvertSrv {
	return &convertSrv{}
}

// 获取报价
func (c *convertSrv) RateDetailed(ctx context.Context, req *api.RateDetailedReq) (*api.RateDetailedRes, error) {
	var (
		url    = global.ViperObj.GetString("forex.baseUrl") + "/v2/rates/detailed"
		err    error
		body   []byte
		obj    *api.RateDetailedRes
		params = make(map[string]string)
	)
	params["buy_currency"] = req.BuyCurrency
	params["sell_currency"] = req.SellCurrency
	params["amount"] = req.Amount
	params["fixed_side"] = req.FixedSide

	body, err = GetRequestToCC(ctx, url, params)
	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err = json.Unmarshal(body, &obj); err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	return obj, err
}

// 报价转化
func (c *convertSrv) Conversions(ctx context.Context, req *api.ConversionsReq) error {
	var (
		url  = global.ViperObj.GetString("forex.baseUrl") + "/v2/conversions/create"
		err  error
		body []byte
		obj  *api.ConversionsRes
	)
	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("buy_currency", req.BuyCurrency)
	_ = writer.WriteField("sell_currency", req.SellCurrency)
	_ = writer.WriteField("fixed_side", req.FixedSide)
	_ = writer.WriteField("amount", req.Amount)
	_ = writer.WriteField("term_agreement", cast.ToString(req.TermAgreement))
	if len(req.ConversionDate) > 0 {
		_ = writer.WriteField("conversion_date", req.ConversionDate)
	}
	if err = writer.Close(); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	body, err = PostRequestToCC(ctx, url, writer.FormDataContentType(), payload)
	if err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if err = json.Unmarshal(body, &obj); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if _, err = global.GFDB.Model("forex_conversion").Insert(&model.ForexConversion{
		ConversionId:      obj.Id,
		SettlementDate:    obj.SettlementDate,
		ConversionDate:    obj.ConversionDate,
		ShortReference:    obj.ShortReference,
		CreatorContactId:  obj.CreatorContactId,
		AccountId:         obj.AccountId,
		CurrencyPair:      obj.CurrencyPair,
		Status:            obj.Status,
		BuyCurrency:       obj.BuyCurrency,
		SellCurrency:      obj.SellCurrency,
		ClientBuyAmount:   obj.ClientBuyAmount,
		ClientSellAmount:  obj.ClientSellAmount,
		FixedSide:         obj.FixedSide,
		CoreRate:          obj.CoreRate,
		PartnerRate:       obj.PartnerRate,
		PartnerBuyAmount:  obj.PartnerBuyAmount,
		PartnerSellAmount: obj.PartnerSellAmount,
		ClientRate:        obj.ClientRate,
		DepositAmount:     obj.DepositAmount,
		DepositCurrency:   obj.DepositCurrency,
		DepositStatus:     obj.DepositStatus,
		DepositRequireAt:  obj.DepositRequiredAt,
		PaymentIds:        strings.Join(obj.PaymentIds, ","),
		UnallocatedFunds:  obj.UnallocatedFunds,
		MidMarketRate:     obj.MidMarketRate,
	}); err != nil {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}
